# 远程部署脚本 - Windows Server 2019
param(
    [string]$ServerIP = "10.3.255.92",
    [string]$RemotePath = "D:\Service\LzfyHisService",
    [string]$Username = "",  # 服务器用户名
    [string]$Password = "",  # 服务器密码
    [switch]$Deploy,
    [switch]$Backup,
    [switch]$TestConnection,
    [switch]$ShowLog
)

$ErrorActionPreference = "Stop"
$LocalPath = $PSScriptRoot
$LogFile = Join-Path $LocalPath "deploy.log"

# 日志函数
function Write-Log {
    param([string]$Message, [string]$Level = "INFO")
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] [$Level] $Message"
    Write-Host $logEntry -ForegroundColor $(if ($Level -eq "ERROR") { "Red" } elseif ($Level -eq "WARN") { "Yellow" } else { "Green" })
    Add-Content -Path $LogFile -Value $logEntry -Force
}

# 创建日志文件
if (-not (Test-Path $LogFile)) {
    New-Item -Path $LogFile -ItemType File -Force
}

Write-Log "=== 开始远程部署流程 ==="
Write-Log "目标服务器: $ServerIP"
Write-Log "远程路径: $RemotePath"

# 测试连接
function Test-ServerConnection {
    Write-Log "测试服务器连接..."
    try {
        $pingResult = Test-Connection -ComputerName $ServerIP -Count 2 -Quiet
        if ($pingResult) {
            Write-Log "服务器连接正常"
            return $true
        } else {
            Write-Log "服务器连接失败" "ERROR"
            return $false
        }
    } catch {
        Write-Log "连接测试异常: $($_.Exception.Message)" "ERROR"
        return $false
    }
}

# 创建远程会话
function New-RemoteSession {
    param([string]$ServerIP, [string]$Username, [string]$Password)
    
    if ([string]::IsNullOrEmpty($Username) -or [string]::IsNullOrEmpty($Password)) {
        Write-Log "请提供服务器用户名和密码" "ERROR"
        Write-Host "使用方法: .\remote-deploy.ps1 -Deploy -Username 'admin' -Password '密码'" -ForegroundColor Yellow
        return $null
    }

    $securePassword = ConvertTo-SecureString $Password -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($Username, $securePassword)
    
    try {
        $session = New-PSSession -ComputerName $ServerIP -Credential $credential -ErrorAction Stop
        Write-Log "远程会话创建成功"
        return $session
    } catch {
        Write-Log "创建远程会话失败: $($_.Exception.Message)" "ERROR"
        return $null
    }
}

# 停止服务
function Stop-RemoteService {
    param([System.Management.Automation.Runspaces.PSSession]$Session)
    
    Write-Log "检查并停止远程服务..."
    $script = @"
    `$service = Get-Service -Name "LzfyHisService" -ErrorAction SilentlyContinue
    if (`$service) {
        if (`$service.Status -eq 'Running') {
            Write-Output "正在停止服务..."
            Stop-Service -Name "LzfyHisService" -Force
            Start-Sleep -Seconds 5
            `$service = Get-Service -Name "LzfyHisService"
            if (`$service.Status -eq 'Stopped') {
                Write-Output "服务已停止"
            } else {
                Write-Output "服务停止失败，状态: $($service.Status)"
            }
        } else {
            Write-Output "服务当前状态: $($service.Status)"
        }
    } else {
        Write-Output "服务未安装"
    }
"@
    
    try {
        $result = Invoke-Command -Session $Session -ScriptBlock { param($s) & ([scriptblock]::Create($s)) } -ArgumentList $script
        Write-Log $result
    } catch {
        Write-Log "停止服务时出错: $($_.Exception.Message)" "WARN"
    }
}

# 备份文件
function Backup-RemoteFiles {
    param([System.Management.Automation.Runspaces.PSSession]$Session)
    
    Write-Log "开始备份远程文件..."
    $script = @"
    `$remotePath = "$RemotePath"
    `$backupPath = "$RemotePath\backup\$(Get-Date -Format 'yyyyMMdd_HHmmss')"
    
    if (Test-Path `$remotePath) {
        if (-not (Test-Path "$RemotePath\backup")) {
            New-Item -Path "$RemotePath\backup" -ItemType Directory -Force
        }
        
        Write-Output "创建备份目录: `$backupPath"
        New-Item -Path `$backupPath -ItemType Directory -Force
        
        # 备份重要文件和配置
        `$itemsToBackup = @(
            "Lzfy_His_Service.exe",
            "*.dll",
            "appsettings*.json",
            "*.config"
        )
        
        foreach (`$item in `$itemsToBackup) {
            `$source = Join-Path `$remotePath `$item
            if (Test-Path `$source) {
                Copy-Item `$source `$backupPath -Recurse -Force
                Write-Output "已备份: `$item"
            }
        }
        
        Write-Output "备份完成: `$backupPath"
        return `$backupPath
    } else {
        Write-Output "远程路径不存在，跳过备份"
        return `$null
    }
"@
    
    try {
        $backupPath = Invoke-Command -Session $Session -ScriptBlock { param($s) & ([scriptblock]::Create($s)) } -ArgumentList $script
        Write-Log "备份完成: $backupPath"
        return $backupPath
    } catch {
        Write-Log "备份文件时出错: $($_.Exception.Message)" "ERROR"
        return $null
    }
}

# 部署文件
function Deploy-Files {
    param([System.Management.Automation.Runspaces.PSSession]$Session)
    
    Write-Log "开始部署文件..."
    
    # 本地构建
    Write-Log "开始本地构建..."
    Set-Location (Split-Path $LocalPath -Parent)
    dotnet publish --configuration Release --output "bin\Release\net9.0\publish" --no-self-contained
    if ($LASTEXITCODE -ne 0) {
        Write-Log "本地构建失败" "ERROR"
        return $false
    }
    Write-Log "本地构建成功"
    
    # 复制文件到远程
    $localPublishPath = Join-Path (Split-Path $LocalPath -Parent) "bin\Release\net9.0\publish"
    
    try {
        $script = @"
        `$remotePath = "$RemotePath"
        
        # 确保远程目录存在
        if (-not (Test-Path `$remotePath)) {
            New-Item -Path `$remotePath -ItemType Directory -Force
            Write-Output "创建远程目录: `$remotePath"
        }
        
        # 确保日志目录存在
        `$logPath = Join-Path `$remotePath "logs"
        if (-not (Test-Path `$logPath)) {
            New-Item -Path `$logPath -ItemType Directory -Force
            Write-Output "创建日志目录: `$logPath"
        }
        
        # 返回远程路径信息
        Write-Output "远程目录准备完成: `$remotePath"
        return `$remotePath
"@
        
        $result = Invoke-Command -Session $Session -ScriptBlock { param($s) & ([scriptblock]::Create($s)) } -ArgumentList $script
        Write-Log $result
        
        # 使用Copy-Item复制文件
        Write-Log "开始复制文件到远程服务器..."
        Copy-Item -Path "$localPublishPath\*" -Destination "\\$ServerIP\D$\Service\LzfyHisService" -Recurse -Force -ErrorAction Stop
        Write-Log "文件复制完成"
        
        return $true
    } catch {
        Write-Log "文件部署失败: $($_.Exception.Message)" "ERROR"
        return $false
    }
}

# 启动服务
function Start-RemoteService {
    param([System.Management.Automation.Runspaces.PSSession]$Session)
    
    Write-Log "启动远程服务..."
    $script = @"
    `$service = Get-Service -Name "LzfyHisService" -ErrorAction SilentlyContinue
    if (`$service) {
        if (`$service.Status -ne 'Running') {
            Write-Output "正在启动服务..."
            Start-Service -Name "LzfyHisService"
            Start-Sleep -Seconds 5
            
            `$service = Get-Service -Name "LzfyHisService"
            if (`$service.Status -eq 'Running') {
                Write-Output "服务启动成功"
                
                # 检查端口
                `$portCheck = Get-NetTCPConnection -LocalPort 6731 -ErrorAction SilentlyContinue
                if (`$portCheck) {
                    Write-Output "服务端口 6731 已监听"
                } else {
                    Write-Output "警告: 服务端口 6731 未监听"
                }
            } else {
                Write-Output "服务启动失败，状态: $($service.Status)"
            }
        } else {
            Write-Output "服务已在运行中"
        }
    } else {
        Write-Output "服务未安装"
    }
"@
    
    try {
        $result = Invoke-Command -Session $Session -ScriptBlock { param($s) & ([scriptblock]::Create($s)) } -ArgumentList $script
        Write-Log $result
    } catch {
        Write-Log "启动服务时出错: $($_.Exception.Message)" "ERROR"
    }
}

# 完整部署流程
function Invoke-FullDeploy {
    Write-Log "开始完整部署流程"
    
    # 测试连接
    if (-not (Test-ServerConnection)) {
        return $false
    }
    
    # 创建远程会话
    $session = New-RemoteSession -ServerIP $ServerIP -Username $Username -Password $Password
    if (-not $session) {
        return $false
    }
    
    try {
        # 1. 停止服务
        Stop-RemoteService -Session $session
        
        # 2. 备份文件
        $backupPath = Backup-RemoteFiles -Session $session
        
        # 3. 部署文件
        $deploySuccess = Deploy-Files -Session $session
        if (-not $deploySuccess) {
            Write-Log "部署失败，回滚操作..." "ERROR"
            return $false
        }
        
        # 4. 启动服务
        Start-RemoteService -Session $session
        
        Write-Log "部署完成"
        Write-Log "备份路径: $backupPath"
        
        return $true
    } finally {
        Remove-PSSession -Session $session
        Write-Log "远程会话已关闭"
    }
}

# 主执行逻辑
if ($TestConnection) {
    Test-ServerConnection
} elseif ($Deploy) {
    Invoke-FullDeploy
} elseif ($Backup) {
    $session = New-RemoteSession -ServerIP $ServerIP -Username $Username -Password $Password
    if ($session) {
        Backup-RemoteFiles -Session $session
        Remove-PSSession -Session $session
    }
} elseif ($ShowLog) {
    if (Test-Path $LogFile) {
        Get-Content $LogFile -Tail 50
    }
} else {
    Write-Host "使用方法:" -ForegroundColor Cyan
    Write-Host "  完整部署: .\remote-deploy.ps1 -Deploy -Username 'admin' -Password '密码'" -ForegroundColor Yellow
    Write-Host "  测试连接: .\remote-deploy.ps1 -TestConnection -Username 'admin' -Password '密码'" -ForegroundColor Yellow
    Write-Host "  仅备份: .\remote-deploy.ps1 -Backup -Username 'admin' -Password '密码'" -ForegroundColor Yellow
    Write-Host "  查看日志: .\remote-deploy.ps1 -ShowLog" -ForegroundColor Yellow
}